home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / tpb4_src.zip / DEARC.PAS < prev    next >
Pascal/Delphi Source File  |  1988-09-13  |  23KB  |  964 lines

  1. { TPBoard 4.2 Copyright (c) 1987,88 by Jon Schneider & Rick Petersen  
  2.   Portions Copyright (c) 1986,87 by Steve Fox and Les Archambault  
  3.   
  4.   Last modified  ::  7-12-88 4:43 pm 
  5. }
  6.  
  7. {$R-}                             {Range checking off}
  8. {$B-}                             {Boolean complete evaluation off}
  9. {$S-}                             {Stack checking off}
  10. {$I+}                             {I/O checking on}
  11. {$N-}                             {No numeric coprocessor}
  12.  
  13. Unit DeArc;
  14.  
  15. Interface
  16.  
  17. Uses
  18.   TPCrt, Dos, Globals, Core1, Core2, TPSTRING;
  19.   
  20.   
  21. procedure TypeArc(var arcname, TypeName : DosFileName);
  22.  
  23.  
  24.   {==========================================================================}
  25.   
  26.   
  27. Implementation
  28.  
  29.  
  30.   procedure TypeArc(var arcname, TypeName : DosFileName);
  31.   
  32.   const
  33.     {.F-}
  34.    blocksize   = $4000;       { size of file buffers in heap }
  35.    arcmarc     = 26;          { special archive marker }
  36.    arcver      = 9;           { max archive header version code }
  37.    strlen      = 100;         { standard string length }
  38.    DLE         = $90;
  39.    error       = -1;
  40.    speof       = 256;
  41.    numvals     = 256;         { 1 less than the number of values }
  42.    tabsize     = 4096;
  43.    tabsizem1   = 4095;
  44.    no_pred     = -1;
  45.    empty       = -1;
  46.    crunch_bits = 12;
  47.    squash_bits = 13;
  48.    init_bits   = 9;
  49.    first       = 257;
  50.    clear       = 256;
  51.    hsizem1     = 8191;
  52.    bitsm1      = 27;
  53.    
  54.    rmask : array[0..8] of Byte
  55.          = ($00, $01, $03, $07, $0f, $1f, $3f, $7f, $ff);
  56.          
  57. type
  58.    strtype     = string[strlen];
  59.    
  60.    entry       = record
  61.                     used : Boolean;
  62.                     next : Integer;
  63.                     predecessor : Integer;
  64.                     follower : Byte;
  65.                   end;
  66.                   
  67.    nd          = record
  68.                     child : array[0..1] of Integer;
  69.                  end;
  70.                  
  71.    buftype     = array[1..blocksize] of Byte;
  72.    prefixtype  = array[0..hsizem1] of Integer;
  73.    suffixtype  = array[0..hsizem1] of Byte;
  74.    stack1type  = array[0..hsizem1] of Byte;
  75.    stacktype   = array[0..tabsizem1] of Byte;
  76.    strtabtype  = array[0..tabsizem1] of entry;
  77.    
  78.    
  79.    bufptr      = ^buftype;                
  80.    prefixptr   = ^prefixtype;
  81.    suffixptr   = ^suffixtype;
  82.    stack1ptr   = ^stack1type;
  83.    stackptr    = ^stacktype;
  84.    strtabptr   = ^strtabtype;
  85.    
  86. var
  87.    strtab_hold                : entry;
  88.    arcfile                    : file;         
  89.    arcbuf                     : bufptr;        
  90.    prefixbuf                  : prefixptr;  
  91.    suffixbuf                  : suffixptr;  
  92.    stack1buf                  : stack1ptr;  
  93.    stackbuf                   : stackptr;
  94.    strtabbuf                  : strtabptr;
  95.    arcptr,                 
  96.    arccount                   : word;        
  97.    extname                    : DosFileName;     
  98.    state                      : (nohist, inrep);
  99.    size                       : longint;
  100.    node                       : array[0..numvals] of nd;
  101.    lastc, bpos, curin,
  102.    numnodes, sp,
  103.    code_count,   
  104.    maxcode, oldcode,
  105.    finchar, clear_flg,
  106.    free_ent, maxcodemax,
  107.    offset, line_count,
  108.    bits, n_bits,
  109.    inbuf                      : Integer;
  110.    firstch, OK, firstc,
  111.    newhash, endfile           : Boolean;      
  112.    buf                        : array[0..bitsm1] of Byte;
  113.    
  114.    {.F+}
  115.    
  116.    
  117.     function Fn_To_Str(var fn : fntype) : strtype;
  118.     
  119.     var
  120.       s               : strtype;
  121.       i               : Integer;
  122.       
  123.     begin
  124.       s := '';
  125.       i := 0;
  126.       while fn[i] <> #0 do
  127.         begin
  128.           s := s+fn[i];
  129.           Inc(i);
  130.         end;
  131.       if Pos('.', s) = 0 then
  132.         s := s+'.';
  133.       Fn_To_Str := s;
  134.     end;
  135.     
  136.     
  137.     procedure Read_Arc_Block;
  138.     
  139.     begin
  140.       if EoF(arcfile) then
  141.         endfile := True
  142.       else
  143.         BlockRead(arcfile, arcbuf^, blocksize, arccount);
  144.       arcptr := 1;
  145.     end;
  146.     
  147.     
  148.     procedure Open_Arc;
  149.     
  150.     begin
  151.       Assign(arcfile, arcname);
  152.       Reset(arcfile, 1);
  153.       endfile := False;
  154.       Read_Arc_Block;             { pre-load buffer }
  155.     end;
  156.     
  157.     
  158.     function Get_Arc : Byte;
  159.     
  160.     begin
  161.       if endfile then
  162.         Get_Arc := 0
  163.       else
  164.         begin
  165.           Get_Arc := arcbuf^[arcptr];
  166.           if arcptr = arccount then
  167.             Read_Arc_Block
  168.           else
  169.             Inc(arcptr)
  170.         end;
  171.     end;
  172.     
  173.     
  174.     procedure Put_Ext(c : Byte);
  175.     
  176.     var
  177.       i               : Integer;
  178.       
  179.     begin
  180.       if OK then
  181.         begin
  182.           if c = Integer(TAB) then
  183.             for i := 1 to (8-(WhereX mod 8)) do
  184.               Write(Com, ' ')
  185.           else if (not(c in [3..7, 11, 14..31])) then
  186.             Write(Com, Chr(c));
  187.           if (user_rec.lines <> 99) and (Chr(c) = LF) then
  188.             begin
  189.               Inc(line_count);
  190.               if line_count mod user_rec.lines = 0 then
  191.                 pause;
  192.               if brk or ((line_count > line_abort) and
  193.                 (line_abort > 0) and (user_rec.access < 255)) then
  194.                 OK := False;
  195.             end;
  196.         end;
  197.     end;
  198.     
  199.     
  200.     procedure Close_Arc;
  201.     
  202.     begin
  203.       {$I-}
  204.       Close(arcfile);
  205.       {$I+}
  206.     end;
  207.     
  208.     
  209.     procedure FSkip(offset : LongInt);
  210.     
  211.     var
  212.       rec             : LongInt;
  213.       
  214.     begin
  215.       if (offset+arcptr) <= arccount then
  216.         arcptr := arcptr+offset
  217.       else
  218.         begin
  219.           rec := FilePos(arcfile)+(offset-(arccount-arcptr)-1);
  220.           {$I-}
  221.           Seek(arcfile, rec);
  222.           {$I+}
  223.           OK := (IoResult = 0);
  224.           if OK then
  225.             Read_Arc_Block;
  226.         end;
  227.     end;
  228.     
  229.     
  230.     procedure FRead(var buf; reclen : Integer);
  231.     
  232.     var
  233.       i               : Integer;
  234.       b               : array[1..28] of Byte absolute buf;
  235.       
  236.     begin
  237.       for i := 1 to reclen do
  238.         b[i] := Get_Arc;
  239.     end;
  240.     
  241.     
  242.     function Read_Hdr(var hdr : heads) : Boolean;
  243.     
  244.     begin
  245.       if OK then
  246.         begin
  247.           if endfile then
  248.             begin
  249.               Read_Hdr := False;  { end of file }
  250.               Exit;
  251.             end;
  252.           if Get_Arc <> arcmarc then
  253.             begin
  254.               WriteLn(Com, 'Missing or invalid header in ', arcname);
  255.               OK := False;
  256.               Exit;
  257.             end;
  258.           hdrver := Get_Arc;
  259.           if hdrver < 0 then
  260.             begin
  261.               WriteLn(Com, 'Missing or invalid header in '+arcname);
  262.               OK := False;
  263.               Exit;
  264.             end;
  265.           if hdrver = 0 then
  266.             begin
  267.               Read_Hdr := False;  { end of file }
  268.               Exit;
  269.             end;
  270.           if hdrver = 1 then
  271.             begin
  272.               FRead(hdr, SizeOf(heads)-SizeOf(LongInt));
  273.               hdrver := 2;
  274.               hdr.Length := hdr.size;
  275.             end
  276.           else
  277.             FRead(hdr, SizeOf(heads));
  278.           Read_Hdr := True;
  279.         end;
  280.     end;
  281.     
  282.     
  283.     procedure Putc_Ncr(c : Integer);
  284.     
  285.     begin
  286.       case state of
  287.         nohist : if c = DLE then
  288.                    state := inrep
  289.                  else
  290.                    begin
  291.                      lastc := c;
  292.                      Put_Ext(c);
  293.                    end;
  294.         inrep :
  295.           begin
  296.             if c = 0 then
  297.               Put_Ext(DLE)
  298.             else
  299.               begin
  300.                 Dec(c);
  301.                 while (c <> 0) and OK do
  302.                   begin
  303.                     Put_Ext(lastc);
  304.                     Dec(c);
  305.                   end;
  306.               end;
  307.             state := nohist
  308.           end;
  309.       end;
  310.     end;
  311.     
  312.     
  313.     function Getc_Unp : Integer;
  314.     
  315.     begin
  316.       if size = 0.0 then
  317.         Getc_Unp := -1
  318.       else
  319.         begin
  320.           Dec(size);
  321.           Getc_Unp := Get_Arc;
  322.         end;
  323.     end;
  324.     
  325.     
  326.     procedure Init_Usq;
  327.     
  328.     var
  329.       i               : Integer;
  330.       
  331.     begin
  332.       bpos := 99;
  333.       FRead(numnodes, SizeOf(numnodes));
  334.       if (numnodes < 0) or (numnodes > numvals) then
  335.         begin
  336.           WriteLn(Com, extname, ' has an invalid decode tree');
  337.           OK := False;
  338.         end
  339.       else
  340.         begin
  341.           node[0].child[0] := -(speof+1);
  342.           node[0].child[1] := -(speof+1);
  343.           for i := 0 to numnodes-1 do
  344.             begin
  345.               FRead(node[i].child[0], SizeOf(Integer));
  346.               FRead(node[i].child[1], SizeOf(Integer));
  347.             end;
  348.         end;
  349.     end;
  350.     
  351.     
  352.     function Getc_Usq : Integer;
  353.     
  354.     var
  355.       i               : Integer;
  356.       
  357.     begin
  358.       i := 0;
  359.       while (i >= 0) and OK do
  360.         begin
  361.           Inc(bpos);
  362.           if bpos > 7 then
  363.             begin
  364.               curin := Getc_Unp;
  365.               if curin = error then
  366.                 begin
  367.                   Getc_Usq := error;
  368.                   Exit;
  369.                 end;
  370.               bpos := 0;
  371.               i := node[i].child[1 and curin];
  372.             end
  373.           else
  374.             begin
  375.               curin := curin shr 1;
  376.               i := node[i].child[1 and curin];
  377.             end;
  378.         end;
  379.       i := -(i+1);
  380.       if i = speof then
  381.         Getc_Usq := -1
  382.       else
  383.         Getc_Usq := i;
  384.     end;
  385.     
  386.     
  387.     function H(Pred, foll : Integer) : Integer;
  388.     
  389.     var
  390.       Local           : Real;
  391.       s               : string[20];
  392.       i, V            : Integer;
  393.       c               : Char;
  394.       
  395.     begin
  396.       if not newhash then
  397.         begin
  398.           Local := (Pred+foll) or $0800;
  399.           if Local < 0.0 then
  400.             Local := Local+65536.0;
  401.           Local := (Local*Local)/64.0;
  402.           Str(Local:15:5, s);
  403.           V := 0;
  404.           i := 1;
  405.           c := s[1];
  406.           while (c <> '.') and OK do
  407.             begin
  408.               if (c >= '0') and (c <= '9') then
  409.                 V := V*10+(Ord(c)-Ord('0'));
  410.               Inc(i);
  411.               c := s[i];
  412.             end;
  413.           H := V and $0FFF;
  414.         end
  415.       else
  416.         begin
  417.           Local := (Pred+foll)*15073;
  418.           Str(Local:15:5, s);
  419.           V := 0;
  420.           i := 1;
  421.           c := s[1];
  422.           while (c <> '.') and OK do
  423.             begin
  424.               if (c >= '0') and (c <= '9') then
  425.                 V := V*10+(Ord(c)-Ord('0'));
  426.               Inc(i);
  427.               c := s[i];
  428.             end;
  429.           H := V and $0FFF;
  430.         end;
  431.     end;
  432.     
  433.     
  434.     function Eolist(index : Integer) : Integer;
  435.     
  436.     var
  437.       temp            : Integer;
  438.       
  439.     begin
  440.       temp := strtabbuf^[index].next;
  441.       while (temp <> 0) and OK do
  442.         begin
  443.           index := temp;
  444.           temp := strtabbuf^[index].next;
  445.         end;
  446.       Eolist := index;
  447.     end;
  448.     
  449.     
  450.     function Hash(Pred, foll : Integer) : Integer;
  451.     
  452.     var
  453.       Local           : Integer;
  454.       tempnext        : Integer;
  455.       
  456.     begin
  457.       Local := H(Pred, foll);
  458.       if not strtabbuf^[local].used then
  459.         Hash := Local
  460.       else
  461.         begin
  462.           Local := Eolist(Local);
  463.           tempnext := (Local+101) and $0FFF;
  464.           while (strtabbuf^[tempnext].used) and OK do
  465.             begin
  466.               Inc(tempnext);
  467.               if tempnext = tabsize then
  468.                 tempnext := 0;
  469.             end;
  470.           strtabbuf^[local].next := tempnext;
  471.           Hash := tempnext;
  472.         end;
  473.     end;
  474.     
  475.     
  476.     procedure Upd_Tab(Pred, foll : Integer);
  477.     
  478.     begin
  479.       with strtabbuf^[Hash(Pred, foll)] do
  480.         begin
  481.           used := True;
  482.           next := 0;
  483.           predecessor := Pred;
  484.           follower := foll;
  485.         end;
  486.     end;
  487.     
  488.     
  489.     function Gocode : Integer;
  490.     
  491.     var
  492.       localbuf        : Integer;
  493.       returnval       : Integer;
  494.       
  495.     begin
  496.       if inbuf = empty then
  497.         begin
  498.           localbuf := Getc_Unp;
  499.           if localbuf = -1 then
  500.             begin
  501.               Gocode := -1;
  502.               Exit;
  503.             end;
  504.           localbuf := localbuf and $00FF;
  505.           inbuf := Getc_Unp;
  506.           if inbuf = -1 then
  507.             begin
  508.               Gocode := -1;
  509.               Exit;
  510.             end;
  511.           inbuf := inbuf and $00FF;
  512.           returnval := ((localbuf shl 4) and $0FF0)+((inbuf shr 4) and $000F);
  513.           inbuf := inbuf and $000F;
  514.         end
  515.       else
  516.         begin
  517.           localbuf := Getc_Unp;
  518.           if localbuf = -1 then
  519.             begin
  520.               Gocode := -1;
  521.               Exit;
  522.             end;
  523.           localbuf := localbuf and $00FF;
  524.           returnval := localbuf+((inbuf shl 8) and $0F00);
  525.           inbuf := empty;
  526.         end;
  527.       Gocode := returnval;
  528.     end;
  529.     
  530.     
  531.     procedure Push(c : Integer);
  532.     
  533.     begin
  534.       stackbuf^[sp] := c;
  535.       Inc(sp);
  536.       if sp >= tabsize then
  537.         begin
  538.           WriteLn(Com, 'Stack overflow');
  539.           OK := False;
  540.         end;
  541.     end;
  542.     
  543.     
  544.     function Pop    : Integer;
  545.     
  546.     begin
  547.       if sp > 0 then
  548.         begin
  549.           Dec(sp);
  550.           Pop := stackbuf^[sp];
  551.         end
  552.       else
  553.         Pop := empty;
  554.     end;
  555.     
  556.     
  557.     procedure Init_Tab;
  558.     
  559.     var
  560.       i               : Integer;
  561.       
  562.     begin
  563.       FillChar(strtab_hold, SizeOf(strtab_hold), 0);
  564.       for i := 0 to tabsizem1 do
  565.         strtabbuf^[i] := strtab_hold;
  566.       for i := 0 to 255 do
  567.         Upd_Tab(no_pred, i);
  568.       inbuf := empty;
  569.       { outbuf := EMPTY }
  570.     end;
  571.     
  572.     
  573.     procedure Init_Ucr(i : Integer);
  574.     
  575.     begin
  576.       newhash := (i = 1);
  577.       sp := 0;
  578.       Init_Tab;
  579.       code_count := tabsize-256;
  580.       firstc := True;
  581.     end;
  582.     
  583.     
  584.     function Getc_Ucr : Integer;
  585.     
  586.     var
  587.       code            : Integer;
  588.       newcode         : Integer;
  589.       
  590.     begin
  591.       if firstc then
  592.         begin
  593.           firstc := False;
  594.           oldcode := Gocode;
  595.           finchar := strtabbuf^[oldcode].follower;
  596.           Getc_Ucr := finchar;
  597.           Exit;
  598.         end;
  599.       if sp = 0 then
  600.         begin
  601.           newcode := Gocode;
  602.           code := newcode;
  603.           if code = -1 then
  604.             begin
  605.               Getc_Ucr := -1;
  606.               Exit;
  607.             end;
  608.           if not strtabbuf^[code].used then
  609.             begin
  610.               code := oldcode;
  611.               Push(finchar);
  612.             end;
  613.           while (strtabbuf^[code].predecessor <> no_pred) and OK do
  614.             with strtabbuf^[code] do
  615.               begin
  616.                 Push(follower);
  617.                 code := predecessor;
  618.               end;
  619.           finchar := strtabbuf^[code].follower;
  620.           Push(finchar);
  621.           if code_count <> 0 then
  622.             begin
  623.               Upd_Tab(oldcode, finchar);
  624.               Dec(code_count);
  625.             end;
  626.           oldcode := newcode;
  627.         end;
  628.       Getc_Ucr := Pop;
  629.     end;
  630.     
  631.     
  632.     function Getcode : Integer;
  633.     
  634.     var
  635.       code, r_off,
  636.       bitsx           : Integer;
  637.       bp              : Byte;
  638.       
  639.     begin
  640.       if firstch then
  641.         begin
  642.           offset := 0;
  643.           sizex := 0;
  644.           firstch := False;
  645.         end;
  646.       bp := 0;
  647.       if (clear_flg > 0) or (offset >= sizex) or (free_ent > maxcode) then
  648.         begin
  649.           if free_ent > maxcode then
  650.             begin
  651.               Inc(n_bits);
  652.               if n_bits = bits then
  653.                 maxcode := maxcodemax
  654.               else
  655.                 maxcode := (1 shl n_bits)-1;
  656.             end;
  657.           if clear_flg > 0 then
  658.             begin
  659.               n_bits := init_bits;
  660.               maxcode := (1 shl n_bits)-1;
  661.               clear_flg := 0;
  662.             end;
  663.             
  664.           sizex := 0;
  665.           code := 0;
  666.           while (sizex < n_bits) and (code <> -1) do
  667.             begin
  668.               code := Getc_Unp;
  669.               if code <> -1 then
  670.                 begin
  671.                   buf[sizex] := code;
  672.                   Inc(sizex)
  673.                 end;
  674.             end;
  675.             
  676.           if sizex <= 0 then
  677.             begin
  678.               Getcode := -1;
  679.               Exit;
  680.             end;
  681.           offset := 0;
  682.           sizex := (sizex shl 3)-(n_bits-1);
  683.         end;
  684.       r_off := offset;
  685.       bitsx := n_bits;
  686.       { get first byte }
  687.       bp := bp+(r_off shr 3);
  688.       r_off := r_off and 7;
  689.       
  690.       { get first parft (low order bits) }
  691.       code := buf[bp] shr r_off;
  692.       Inc(bp);
  693.       bitsx := bitsx-(8-r_off);
  694.       r_off := 8-r_off;
  695.       
  696.       if bitsx >= 8 then
  697.         begin
  698.           code := code or (buf[bp] shl r_off);
  699.           Inc(bp);
  700.           r_off := r_off+8;
  701.           bitsx := bitsx-8;
  702.         end;
  703.       code := code or ((buf[bp] and rmask[bitsx]) shl r_off);
  704.       offset := offset+n_bits;
  705.       Getcode := code;
  706.     end;
  707.     
  708.     
  709.     procedure Decomp(squashflag : Integer);
  710.     
  711.     var
  712.       stackp,
  713.       finchar         : Integer;
  714.       code,
  715.       oldcode,
  716.       incode          : Integer;
  717.       
  718.     begin
  719.       if squashflag = 0 then
  720.         bits := crunch_bits
  721.       else
  722.         bits := squash_bits;
  723.         
  724.       if firstch then
  725.         maxcodemax := 1 shl bits;
  726.         
  727.       if squashflag = 0 then
  728.         begin
  729.           code := Getc_Unp;
  730.           if code <> bits then
  731.             begin
  732.               WriteLn(Com, extname, ' packed with ', code, ' bits, I can only handle ', bits);
  733.               Exit;
  734.             end;
  735.         end;
  736.       clear_flg := 0;
  737.       n_bits := init_bits;
  738.       maxcode := (1 shl n_bits)-1;
  739.       for code := 255 downto 0 do
  740.         begin
  741.           prefixbuf^[code] := 0;
  742.           suffixbuf^[code] := code;
  743.         end;
  744.         
  745.       free_ent := first;
  746.       oldcode := Getcode;
  747.       finchar := oldcode;
  748.       if oldcode = -1 then
  749.         Exit;
  750.       if squashflag = 0 then
  751.         Putc_Ncr(finchar)
  752.       else
  753.         Put_Ext(finchar);
  754.       stackp := 0;
  755.       
  756.       code := Getcode;
  757.       while (code > -1) and OK do
  758.         begin
  759.           if code = clear then
  760.             begin
  761.               for code := 255 downto 0 do
  762.                 prefixbuf^[code] := 0;
  763.               clear_flg := 1;
  764.               free_ent := first-1;
  765.               code := Getcode;
  766.             end;
  767.           incode := code;
  768.           if code >= free_ent then
  769.             begin
  770.               stack1buf^[stackp] := finchar;
  771.               Inc(stackp);
  772.               code := oldcode;
  773.             end;
  774.           while (code >= 256) and OK do
  775.             begin
  776.               stack1buf^[stackp] := suffixbuf^[code];
  777.               Inc(stackp);
  778.               code := prefixbuf^[code];
  779.             end;
  780.           finchar := suffixbuf^[code];
  781.           stack1buf^[stackp] := finchar;
  782.           Inc(stackp);
  783.           repeat
  784.             Dec(stackp);
  785.             if squashflag = 0 then
  786.               Putc_Ncr(stack1buf^[stackp])
  787.             else
  788.               Put_Ext(stack1buf^[stackp]);
  789.           until (stackp <= 0) or (not OK);
  790.           code := free_ent;
  791.           if code < maxcodemax then
  792.             begin
  793.               prefixbuf^[code] := oldcode;
  794.               suffixbuf^[code] := finchar;
  795.               free_ent := code+1;
  796.             end;
  797.           oldcode := incode;
  798.           code := Getcode;
  799.         end;
  800.     end;
  801.     
  802.     
  803.     procedure Unpack(var hdr : heads);
  804.     
  805.     var
  806.       c               : Integer;
  807.       
  808.     begin
  809.       size := hdr.size;
  810.       state := nohist;
  811.       firstch := True;
  812.       case hdrver of
  813.         1, 2 :
  814.           begin
  815.             c := Getc_Unp;
  816.             while (c <> -1) and OK do
  817.               begin
  818.                 Put_Ext(c);
  819.                 c := Getc_Unp;
  820.               end;
  821.           end;
  822.         3 :
  823.           begin
  824.             c := Getc_Unp;
  825.             while (c <> -1) and OK do
  826.               begin
  827.                 Putc_Ncr(c);
  828.                 c := Getc_Unp;
  829.               end;
  830.           end;
  831.         4 :
  832.           begin
  833.             Init_Usq;
  834.             c := Getc_Usq;
  835.             while (c <> -1) and OK do
  836.               begin
  837.                 Putc_Ncr(c);
  838.                 c := Getc_Usq;
  839.               end;
  840.           end;
  841.         5 :
  842.           begin
  843.             Init_Ucr(0);
  844.             c := Getc_Ucr;
  845.             while (c <> -1) and OK do
  846.               begin
  847.                 Put_Ext(c);
  848.                 c := Getc_Ucr;
  849.               end;
  850.           end;
  851.         6 :
  852.           begin
  853.             Init_Ucr(0);
  854.             c := Getc_Ucr;
  855.             while (c <> -1) and OK do
  856.               begin
  857.                 Putc_Ncr(c);
  858.                 c := Getc_Ucr;
  859.               end;
  860.           end;
  861.         7 :
  862.           begin
  863.             Init_Ucr(1);
  864.             c := Getc_Ucr;
  865.             while (c <> -1) and OK do
  866.               begin
  867.                 Putc_Ncr(c);
  868.                 c := Getc_Ucr;
  869.               end;
  870.           end;
  871.         8 :
  872.           begin
  873.             Decomp(0);
  874.           end;
  875.         9 :
  876.           begin
  877.             Decomp(1);
  878.           end;
  879.       end;
  880.     end;
  881.     
  882.     
  883.     procedure Extract_File(var hdr : heads);
  884.     
  885.     begin
  886.       if TypeName = extname then
  887.         Unpack(hdr)
  888.       else
  889.         FSkip(hdr.size);
  890.     end;
  891.     
  892.     
  893.     function Verify_File(var hdr : heads) : Boolean;
  894.     
  895.     begin
  896.       Verify_File := True;        { default case }
  897.       extname := Fn_To_Str(hdr.name);
  898.       extname := StUpcase(extname);
  899.       if hdrver > arcver then
  900.         begin
  901.           WriteLn(Com, 'Skipping: '+extname+' -- New version.');
  902.           Verify_File := False;
  903.         end;
  904.     end;
  905.     
  906.     
  907.     procedure init;
  908.     
  909.     begin
  910.       OK := True;
  911.       WriteLn(Com);
  912.       New(strtabbuf);
  913.       New(arcbuf);
  914.       New(prefixbuf);
  915.       New(suffixbuf);
  916.       New(stack1buf);
  917.       New(stackbuf);
  918.       line_count := 0
  919.     end;
  920.     
  921.     
  922.     procedure Extract_Arc;
  923.     
  924.     var
  925.       hdr             : heads;
  926.       
  927.     begin
  928.       Open_Arc;
  929.       while (Read_Hdr(hdr)) and OK do
  930.         if Verify_File(hdr) then
  931.           Extract_File(hdr)
  932.         else
  933.           FSkip(hdr.size);
  934.       Close_Arc;
  935.     end;
  936.     
  937.     
  938.     procedure deinit;
  939.     
  940.     begin
  941.       Dispose(stackbuf);
  942.       Dispose(stack1buf);
  943.       Dispose(suffixbuf);
  944.       Dispose(prefixbuf);
  945.       Dispose(arcbuf);
  946.       Dispose(strtabbuf);
  947.     end;
  948.     
  949.     
  950.   begin
  951.     init;
  952.     Extract_Arc;
  953.     if brk or ((line_count > line_abort) and (line_abort > 0) and
  954.       (user_rec.access < 255)) then
  955.       begin
  956.         WriteLn(Com);
  957.         WriteLn(Com, 'Sorry, you can only ''Type'' ', line_abort, ' lines.');
  958.       end;
  959.     deinit;
  960.   end;
  961.   
  962. end.                              { of DEARC.PAS }
  963. 
  964.